﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using GigaSite.Domain.Entities;
using GigaSite.Domain.Enums;
using GigaSite.Web.Areas.ControlPanel.Models;
using GigaSite.Web.Controllers;
using GigaSite.Web.Models;

namespace GigaSite.Web.Classes
{
    /// <summary>
    /// Содержит расширения HTML хелпера
    /// </summary>
    public static class HtmlHelper
    {
        #region Контроллы

        /// <summary>
        /// Выводит выпадающий список содержащий значения указанного перечисления
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <typeparam name="TEnum">Тип перечисления</typeparam>
        /// <param name="htmlHelper">HtmlHelper</param>
        /// <param name="expression">Выражение</param>
        /// <returns>Строка содержащая HTML разметку с компонентом</returns>
        public static MvcHtmlString DropDownListForEnum<TModel,TEnum>(this HtmlHelper<TModel> htmlHelper,Expression<Func<TModel, TEnum>> expression)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum)).Cast<TEnum>();

            IEnumerable<SelectListItem> items =
                values.Select(value => new SelectListItem
                {
                    Text = value.GetEnumMemberName(),
                    Value = value.ToString(),
                    Selected = value.Equals(metadata.Model)
                });

            return htmlHelper.DropDownListFor(
                expression,
                items
                );
        }

        /// <summary>
        /// Генерирует компонент типа Datepicker
        /// </summary>
        /// <typeparam name="TModel">Модель</typeparam>
        /// <param name="htmlHelper">HTML helper</param>
        /// <param name="expression">Выражение ведущее к дате</param>
        /// <returns>Значение выражения</returns>
        public static MvcHtmlString DatePickerFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, DateTime?>> expression)
        {
            return htmlHelper.TextBoxFor(expression, new {@class = "datepicker"});
        }

        /// <summary>
        /// Генерирует разметку для картинки с провайдером предоставления авторизации
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="htmlHelper"></param>
        /// <param name="identityProvider"></param>
        /// <returns></returns>
        public static MvcHtmlString GetAccountProviderIcon<TModel>(this HtmlHelper<TModel> htmlHelper, string identityProvider)
        {
            string imgUrl = "/Content/images/g.png";

            if (identityProvider.Contains("yandex"))
                imgUrl = "http://loginza.ru/img/providers/yandex.png";

            if (identityProvider.Contains("google"))
                imgUrl = "http://loginza.ru/img/providers/google.png";

            if (identityProvider.Contains("vkontakte"))
                imgUrl = "http://loginza.ru/img/providers/vkontakte.png";

            if (identityProvider.Contains("mail.ru"))
                imgUrl = "http://loginza.ru/img/providers/mailru.png";

            if (identityProvider.Contains("twitter"))
                imgUrl = "http://loginza.ru/img/providers/twitter.png";

            if (identityProvider.Contains("loginza"))
                imgUrl = "http://loginza.ru/img/providers/loginza.png";

            if (identityProvider.Contains("myopenid"))
                imgUrl = "http://loginza.ru/img/providers/myopenid.png";

            if (identityProvider.Contains("openid"))
                imgUrl = "http://loginza.ru/img/providers/openid.png";

            if (identityProvider.Contains("webmoney"))
                imgUrl = "http://loginza.ru/img/providers/webmoney.png";

            if (identityProvider.Contains("facebook"))
                imgUrl = "http://loginza.ru/img/providers/facebook.png";

            return MvcHtmlString.Create(string.Format("<img src=\"{0}\" cssClass=\"provider\" alt=\"]\"/>",imgUrl));
        }

        /// <summary>
        /// Возвращает кусок Html кода представляющий собой ссылку но по нажатию на которой происходит указанное JavaScript действие
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <param name="htmlHelper">Html htlper</param>
        /// <param name="text">Текст, который установить на ссылку</param>
        /// <param name="onClickText">Текст который поместить в событие OnClick</param>
        /// <param name="attributes">Атрибуты которые добавить к элементу</param>
        /// <returns>span оформленный в виде ссылки</returns>
        public static MvcHtmlString JavaScriptLink<TModel>(this HtmlHelper<TModel> htmlHelper, string text, string onClickText, IDictionary<string,string> attributes = null)
        {
            var tagBuilder = new TagBuilder("span");
            tagBuilder.AddCssClass("link");
            tagBuilder.SetInnerText(text);
            tagBuilder.Attributes.Add("onclick",onClickText);
            if (attributes != null)
                tagBuilder.MergeAttributes(attributes,true);
            return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.Normal));
        }

        public static MvcHtmlString MenuItem<TModel>(this HtmlHelper<TModel> htmlHelper, string text, string action, string controller, string cssClass = "", string id = "", string area = "")
        {
            var li = new TagBuilder("li");
            var routeData = htmlHelper.ViewContext.RouteData;
            var currentAction = routeData.GetRequiredString("action");
            var currentController = routeData.GetRequiredString("controller");
            IDictionary<string, string> menuItemCountName = new Dictionary<string, string>
                                                                {
                                                                    // TODO remove hardcoding
                                                                    {"goods", "9949 товаров"},
                                                                    {"shops", "234 магазинов"},
                                                                    {"services", "345 предложений"},
                                                                    {"jobs", "167 вакансий"},
                                                                    {"cards", "345 визиток"},
                                                                    {"sites", "12345 сайтов"},
                                                                    {"ads", "685 объявлений"},
                                                                };
            string menuItemCount = "";

            //if (string.Equals(currentAction, action, StringComparison.OrdinalIgnoreCase) &&
            //    string.Equals(currentController, controller, StringComparison.OrdinalIgnoreCase))
            //{
            //    li.AddCssClass("active");
            //    if (cssClass.Length > 0)
            //    {
            //        li.AddCssClass(cssClass);
            //    }
            //    if (id.Length > 0)
            //    {
            //        string count = menuItemCountName[id];
            //        menuItemCount = htmlHelper.Raw("<div class='count'>" + count + "</div>").ToHtmlString();
            //        li.GenerateId(id);
            //    }
            //    else
            //    {
            //        menuItemCount = "";
            //    }
            //}

            if (currentController.ToLower() == controller.ToLower())
            {
                li.AddCssClass("active");
                if (cssClass.Contains("leftMenuItem"))
                {
                    li.AddCssClass("leftMenuItemActive");
                }
                if (cssClass.Contains("rightMenuItem"))
                {
                    li.AddCssClass("rightMenuItemActive");
                }
            }
            if (cssClass.Length > 0)
            {
                li.AddCssClass(cssClass);
            }
            if (id.Length > 0)
            {
                string count = menuItemCountName[id];
                menuItemCount = htmlHelper.Raw("<div class='count'>" + count + "</div>").ToHtmlString();
                li.GenerateId(id);
            }
            else
            {
                menuItemCount = "";
            }

            li.InnerHtml = htmlHelper.ActionLink(text, action, controller,new {area = area},null).ToHtmlString()
                           + htmlHelper.Raw("<div class='arrow'></div>").ToHtmlString()
                           + menuItemCount;
            return MvcHtmlString.Create(li.ToString());
        }


        /// <summary>
        /// Рендерит элемент персонального меню
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <param name="htmlHelper">Хтмл хелпер</param>
        /// <param name="text">Текст</param>
        /// <param name="action">Экшн</param>
        /// <param name="controller">Контроллер</param>
        /// <param name="cssClass">CSS класс</param>
        /// <param name="id">Идентификатор выходного элемента</param>
        /// <param name="count">число чего либо что отображать после</param>
        /// <param name="area">Зона сайта</param>
        /// <returns>Разметка элемента</returns>
        public static MvcHtmlString PersonalMenuItem<TModel>(this HtmlHelper<TModel> htmlHelper, string text, string action, string controller, string cssClass = "", string id = "", int count = 0, string area = "")
        {
            var li = new TagBuilder("li");
            if (!string.IsNullOrEmpty(cssClass))
            {
                li.AddCssClass(cssClass);
            }
            if (!string.IsNullOrEmpty(id))
            {
                li.MergeAttribute("id",id);
            }

            var innerContent = new StringBuilder();
            innerContent.Append(htmlHelper.ActionLink(text,action,controller,new {area = area},null).ToHtmlString());
            if (count > 0)
            {
                innerContent.AppendFormat("<span class=\"count\">{0}</span>",count);
            }
            li.InnerHtml = innerContent.ToString();

            return MvcHtmlString.Create(li.ToString(TagRenderMode.Normal));
        }

        /// <summary>
        /// разделитель в персональном пользовательском меню
        /// </summary>
        /// <typeparam name="TModel">Модель</typeparam>
        /// <param name="htmlHelper">Хелпер</param>
        /// <returns>Разметка</returns>
        public static MvcHtmlString PersonalMenuSeparator<TModel>(this HtmlHelper<TModel> htmlHelper)
        {
            var li = new TagBuilder("li");
            li.AddCssClass("separator");
            li.InnerHtml = "&nbsp;";

            return MvcHtmlString.Create(li.ToString(TagRenderMode.Normal));
        }

        #endregion

        #region Вспомогательные методы

        /// <summary>
        /// Проверяет добавлена ли указанная визитка в визитницу пользователя
        /// </summary>
        /// <typeparam name="TModel">Модель</typeparam>
        /// <param name="htmlHelper">Помошник HTML</param>
        /// <param name="cardModel">Модель карточки</param>
        /// <returns>true если добавлена, иначе false</returns>
        public static bool CardInBusinessCardsCatalog<TModel>(this HtmlHelper<TModel> htmlHelper, BusinessCardModel cardModel)
        {
            var currentUser = htmlHelper.ViewContext.GetBaseController().CurrentUser;
            return currentUser.BusinessCardToUserMappings.Any(m => m.CardId == cardModel.Id);
        }

        /// <summary>
        /// Возвращает статус текущего авторизованного пользователя
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <param name="htmlHelper">Html помошник</param>
        /// <returns>true если пользователь авторизован, иначе false</returns>
        public static bool IsUserAuthorized<TModel>(this HtmlHelper<TModel> htmlHelper)
        {
            return htmlHelper.ViewContext.GetBaseController().CurrentUser != null;
        }

        /// <summary>
        /// Возвращает содержимое блокнота сайтов текущего пользователя. Если пользователь не авторизован - возвращается пустое перечисление
        /// </summary>
        /// <typeparam name="TModel">Модель</typeparam>
        /// <param name="htmlHelper">Html помощник</param>
        /// <returns></returns>
        public static IEnumerable<SiteModel> GetUserSites<TModel>(this HtmlHelper<TModel> htmlHelper)
        {
            // Проверяем
            var currentUser = htmlHelper.ViewContext.GetBaseController().CurrentUser;
            if (currentUser == null)
            {
                return Enumerable.Empty<SiteModel>();
            }

            // Отдаем
            return currentUser.SiteToUserMappings.OrderBy(m => m.Position).Select(m => m.Site).Where(s => s.Status == SiteStatuses.Active).Select(s => new SiteModel(s));
        }

        /// <summary>
        /// Генерирует разметку для элемента на рабочей панели пользователя
        /// </summary>
        /// <typeparam name="TModel">Тип модели вьюхи</typeparam>
        /// <param name="htmlHelper">Html helper</param>
        /// <param name="itemModel">Модель элемента рабочей панели</param>
        /// <returns>Разметка</returns>
        public static MvcHtmlString WorkbenchItem<TModel>(this HtmlHelper<TModel> htmlHelper,WorkbenchItemModel itemModel)
        {
            return htmlHelper.Partial("WorkbenchItem", itemModel);
        }

        #endregion

        #region Категории

        /// <summary>
        /// Выводит селектор категорий
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <param name="htmlHelper">Html helper</param>
        /// <param name="parentCategory">Родительская категория, дочерние категории которой нужно отрендерить</param>
        /// <param name="urlPrefix">Формат урла, который будет сгенерирован для линка перехода к категории категории</param>
        /// <returns></returns>
        public static MvcHtmlString CategoriesSelector<TModel>(this HtmlHelper<TModel> htmlHelper, Category parentCategory, string urlPrefix)
        {
            return htmlHelper.Partial("CategoriesSelector", new CategoriesHtmlHelperModel()
                                                                {
                                                                    Categories = parentCategory.ChildCategories.OrderBy(c => c.DisplayName).ToList(),
                                                                    UrlFormat = urlPrefix
                                                                });
        }

        /// <summary>
        /// Выводит хлебную крошку для категорий через все ее родительские категории до суперкатегории
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <param name="htmlHelper">Html helper</param>
        /// <param name="category">Категория</param>
        /// <param name="urlFormat">Формат URL для каждой категории</param>
        /// <returns></returns>
        public static MvcHtmlString CategoryBreadcrumph<TModel>(this HtmlHelper<TModel> htmlHelper, Category category, string urlFormat)
        {
            // Строим путь до родительской суперкатегории
            var list = new List<Category>();
            Category currentCategory = category;
            while(currentCategory.ParentId != -1)
            {
                list.Insert(0,currentCategory);
                currentCategory = currentCategory.ParentCategory;
            }
            // Отдаем все это во вью
            return htmlHelper.Partial("CategoryBreadcrumph", new CategoriesHtmlHelperModel()
                                                                {
                                                                    Categories = list,
                                                                    UrlFormat = urlFormat
                                                                });
        }

        #endregion

        #region Navigation Chain

        /// <summary>
        /// Рендерит навигационную цепочку
        /// </summary>
        /// <typeparam name="TModel">Тип модели</typeparam>
        /// <param name="htmlHelper">ХТМЛ Хелпер</param>
        /// <returns>Разметка навигационной цепочки</returns>
        public static MvcHtmlString NavigationChain<TModel>(this HtmlHelper<TModel> htmlHelper)
        {
            return htmlHelper.Partial("NavigationChain");
        }

        #endregion

    }
}


    
